/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mytoutou.playermanager.player_manager.ui;

import com.mytoutou.playermanager.player_manager.utils.Logger;
import ohos.agp.components.AttrSet;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.SurfaceOps;
import ohos.agp.graphics.TextureHolder;
import ohos.app.Context;

import java.util.Optional;

public class TextureView extends SurfaceProvider {
    /**
     * MediaPlayerWrapper instance.
     * Also you should call it from background thread to avoid ANR
     */
    protected MediaPlayerWrapper mMediaPlayer;

    private static final String LOG_TAG = "TextureView";

    protected SurfaceTextureListener mLocalSurfaceTextureListener;

    private TextureHolder mSurface;

    public TextureView(Context context) {
        super(context);
        Optional surfaceHolderOptional = getSurfaceOps();
        SurfaceOps surfaceHolder = (SurfaceOps) surfaceHolderOptional.get();
        surfaceHolder.addCallback(new SurfaceOps.Callback() {
            @Override
            public void surfaceCreated(SurfaceOps surfaceOps) {
                Logger.v(LOG_TAG, "onSurfaceCreated");
                mLocalSurfaceTextureListener.onSurfaceTextureAvailable(surfaceOps, getWidth(), getHeight());
            }

            @Override
            public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {
                Logger.v(LOG_TAG, "surfaceChanged");

            }

            @Override
            public void surfaceDestroyed(SurfaceOps surfaceOps) {
                Logger.v(LOG_TAG, "surfaceDestroyed");
                mLocalSurfaceTextureListener.onSurfaceTextureDestroyed(surfaceOps);
            }
        });
    }

    public TextureView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        Optional surfaceHolderOptional = getSurfaceOps();
        SurfaceOps surfaceHolder = (SurfaceOps) surfaceHolderOptional.get();
        surfaceHolder.addCallback(new SurfaceOps.Callback() {
            @Override
            public void surfaceCreated(SurfaceOps surfaceOps) {
                Logger.v(LOG_TAG, "onSurfaceCreated");
                mLocalSurfaceTextureListener.onSurfaceTextureAvailable(surfaceOps, getWidth(), getHeight());
            }

            @Override
            public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {
                Logger.v(LOG_TAG, "surfaceChanged");

            }

            @Override
            public void surfaceDestroyed(SurfaceOps surfaceOps) {
                Logger.v(LOG_TAG, "surfaceDestroyed");
                mLocalSurfaceTextureListener.onSurfaceTextureDestroyed(surfaceOps);
            }
        });
    }

    public TextureHolder getSurfaceTexture() {
        boolean createNewSurface = (mSurface == null);
        if (createNewSurface) {
            // Create a new SurfaceTexture for the layer.
            mSurface = new TextureHolder(0);
        }
        getSurfaceOps().get().getSurface().bindToTextureHolder(mSurface);

        mSurface.setBufferDimension(getWidth(), getHeight());
        mSurface.setOnNewFrameCallback(surfaceTexture -> {
            invalidate();
        });
        return mSurface;
    }

    private void releaseSurfaceTexture() {
        if (mSurface != null) {
            boolean shouldRelease = true;

            if (mLocalSurfaceTextureListener != null) {
                //shouldRelease = mLocalSurfaceTextureListener.onSurfaceTextureDestroyed(mSurface);
            }

            if (shouldRelease) {
                mSurface.abandon();
            }
            mSurface = null;
        }
    }


    public SurfaceTextureListener getSurfaceTextureListener() {
        return mLocalSurfaceTextureListener;
    }

    public void setSurfaceTextureListener(SurfaceTextureListener listener) {
        mLocalSurfaceTextureListener = listener;
    }


    public interface SurfaceTextureListener {
        /**
         * Invoked when a {@link TextureView}'s SurfaceTexture is ready for use.
         *
         * @param surface The surface returned by
         * @param width   The width of the surface
         * @param height  The height of the surface
         */
        void onSurfaceTextureAvailable(SurfaceOps surface, int width, int height);


        void onSurfaceTextureSizeChanged(SurfaceOps surface, int width, int height);


        boolean onSurfaceTextureDestroyed(SurfaceOps surface);

        /**
         * Invoked when the specified {@link TextureHolder} is updated through
         * {@link TextureHolder#()}.
         *
         * @param surface The surface just updated
         */
        void onSurfaceTextureUpdated(SurfaceOps surface);
    }


}
